﻿// DlgImport.cpp: 实现文件
//

#include "pch.h"
#include "PE_Studio.h"
#include "PE_StudioDlg.h"
#include "afxdialogex.h"
#include "DlgImport.h"



// DlgImport 对话框

IMPLEMENT_DYNAMIC(DlgImport, CDialogEx)

DlgImport::DlgImport(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DLG_IMPORT, pParent)
{

}

DlgImport::~DlgImport()
{
}

void DlgImport::DoDataExchange(CDataExchange* pDX)
{
	// 调用基类的DoDataExchange方法
	CDialogEx::DoDataExchange(pDX);
	
	// 将IDC_LIST_IMPORT关联到m_ListImport控件
	// 这使得在对话框数据交换过程中，列表控件可以正确地更新和获取数据
	DDX_Control(pDX, IDC_LIST_IMPORT_DLLNAME, m_ListImport);

	// 将 IDC_LIST_IMPORT_FUNCTION 关联到m_ListThunk控件
	// 同样，这确保了Thunk列表控件的数据交换功能正常运行
	DDX_Control(pDX, IDC_LIST_IMPORT_FUNCTION, m_ListThunk);
}


BEGIN_MESSAGE_MAP(DlgImport, CDialogEx)
	ON_NOTIFY(NM_CLICK, IDC_LIST_IMPORT_DLLNAME, &DlgImport::OnNMClickListImport)
END_MESSAGE_MAP()


// DlgImport 消息处理程序


BOOL DlgImport::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	m_ListImport.SetListCtrl(TRUE, TRUE, FALSE, FALSE, TRUE);		// 禁止排序
	m_ListImport.EnableContextMenu(TRUE);
	m_ListImport.InsertColumn(0, TEXT(""), LVCFMT_CENTER, 50);
	m_ListImport.InsertColumn(1, TEXT("NO."), LVCFMT_CENTER, 50);
	m_ListImport.InsertColumn(2, TEXT("OriginalFirstThunk"), LVCFMT_CENTER, 100);
	m_ListImport.InsertColumn(3, TEXT("TimeDateStamp"), LVCFMT_CENTER, 120);
	m_ListImport.InsertColumn(4, TEXT("ForwarderChain"), LVCFMT_CENTER, 100);
	m_ListImport.InsertColumn(5, TEXT("Dll Name"), LVCFMT_CENTER, 100);
	m_ListImport.InsertColumn(6, TEXT("FirstThunk"), LVCFMT_CENTER, 80);
	m_ListImport.DeleteColumn(0);

	m_ListThunk.SetListCtrl(TRUE, TRUE, FALSE, FALSE, TRUE);		// 禁止排序
	m_ListThunk.EnableContextMenu(TRUE);
	m_ListThunk.InsertColumn(0, TEXT(""), LVCFMT_CENTER, 50);
	m_ListThunk.InsertColumn(1, TEXT("NO."), LVCFMT_CENTER, 50);
	m_ListThunk.InsertColumn(2, TEXT("ThunkRva"), LVCFMT_CENTER, 100);
	m_ListThunk.InsertColumn(3, TEXT("ThunkOffset"), LVCFMT_CENTER, 100);
	m_ListThunk.InsertColumn(4, TEXT("ThunkValue"), LVCFMT_CENTER, 100);
	m_ListThunk.InsertColumn(5, TEXT("Hint"), LVCFMT_CENTER, 60);
	m_ListThunk.InsertColumn(6, TEXT("ApiName"), LVCFMT_CENTER, 140);
	m_ListThunk.DeleteColumn(0);
    
	InitImportTable();
    
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

void DlgImport::InitImportTable()
{
	m_ListImport.DeleteAllItems();
    
	//获取导入函数表在内存文件中的偏移
	CPEStudioDlg* pHwndParent = (CPEStudioDlg*)(AfxGetApp()->GetMainWnd());	// 父窗口句柄
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = pHwndParent->m_pPE->m_pImportDescriptor;
    CString szTemp = TEXT("");
	int i = 0;
	BYTE* pName = {0};
	while (!IsEndOfTable(&pImportDesc[i]))
	{
        // NO.
		szTemp.Format(TEXT("%d"), i + 1);
        m_ListImport.InsertItem(i, szTemp);
        
		// OriginalFirstThunk
		szTemp.Format(TEXT("%08X"), pImportDesc[i].OriginalFirstThunk);
		m_ListImport.SetItemText(i, 1, szTemp);

		// TimeDateStamp
		szTemp.Format(TEXT("%08X"), pImportDesc[i].TimeDateStamp);
		m_ListImport.SetItemText(i, 2, szTemp);

		// TimeDateStamp
		//tm Tm;
		//gmtime_s(&Tm, (time_t*)&pImportDesc[i].TimeDateStamp);
		//TCHAR szBuffer[MAX_PATH] = { 0 };
		//_tcsftime(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), TEXT("%Y/%m/%d %H:%M:%S"), &Tm);
		//m_ListImport.SetItemText(i, 2, szBuffer);

		// ForwarderChain
		szTemp.Format(TEXT("%08X"), pImportDesc[i].ForwarderChain);
		m_ListImport.SetItemText(i, 3, szTemp);

        // Dll Name
		pName = (BYTE*)(pHwndParent->m_pPE->RVAtoFOA(pImportDesc[i].Name, (DWORD)pHwndParent->m_pPE->m_pImageBase));
		
		if (NULL == pName)
		{
			m_ListImport.SetItemText(i, 4, TEXT("-"));
		}
		else
		{
			m_ListImport.SetItemText(i, 4, (CString)pName);
		}
        
		// FirstThunk
		szTemp.Format(TEXT("%08X"), pImportDesc[i].FirstThunk);
		m_ListImport.SetItemText(i, 5, szTemp);
        
		i++;        
	}
}

void DlgImport::InitImportThunk(int nIndex)
{
	m_ListThunk.DeleteAllItems();

	CString szTemp = TEXT("");
	int i = 0;
	//获取导入函数表在内存文件中的偏移
	CPEStudioDlg* pHwndParent = (CPEStudioDlg*)(AfxGetApp()->GetMainWnd());	// 父窗口句柄
	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = pHwndParent->m_pPE->m_pImportDescriptor;
	PIMAGE_THUNK_DATA pThunkData = (PIMAGE_THUNK_DATA)pHwndParent->m_pPE->RVAtoFOA(pImportDesc[nIndex].OriginalFirstThunk, (DWORD)pHwndParent->m_pPE->m_pImageBase);	// 指向OriginalFirstThunk的指针
	if (NULL == pThunkData)
	{
		pThunkData = (PIMAGE_THUNK_DATA)pHwndParent->m_pPE->RVAtoFOA(pImportDesc[nIndex].FirstThunk, (DWORD)pHwndParent->m_pPE->m_pImageBase);	// 指向OriginalFirstThunk的指针
		if (NULL == pThunkData) return;
	}
	while (NULL != pThunkData->u1.AddressOfData)	//u1 = _IMAGE_THUNK_DATA32
	{	
		i = m_ListThunk.GetItemCount();
        // NO.
        szTemp.Format(TEXT("%d"), i + 1);
        m_ListThunk.InsertItem(i, szTemp);
        
        // ThunkRVA
        szTemp.Format(TEXT("%08X"), pHwndParent->m_pPE->FOAtoRVA((DWORD)pThunkData - (DWORD)pHwndParent->m_pPE->m_pImageBase));
        m_ListThunk.SetItemText(i, 1, szTemp);
        
        // ThunkOffset
        szTemp.Format(TEXT("%08X"), (DWORD)pThunkData - (DWORD)pHwndParent->m_pPE->m_pImageBase);
        m_ListThunk.SetItemText(i, 2, szTemp);
        
        // ThunkValue
        szTemp.Format(TEXT("%08X"), pThunkData->u1.AddressOfData);
        m_ListThunk.SetItemText(i, 3, szTemp);
        
        
		PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)pHwndParent->m_pPE->RVAtoFOA(pThunkData->u1.AddressOfData, (DWORD)pHwndParent->m_pPE->m_pImageBase);
		if (0 == (pThunkData->u1.AddressOfData & 0x80000000))
        {
			// Hint
			szTemp.Format(TEXT("%04X"), pImportByName->Hint);
			m_ListThunk.SetItemText(i, 4, szTemp);

			// ApiName
			m_ListThunk.SetItemText(i, 5, (CString)pImportByName->Name);
        }
		else
		{
            // Hint
			szTemp.Format(TEXT("Ordinal:%04X"), IMAGE_ORDINAL(pThunkData->u1.AddressOfData));
			m_ListThunk.SetItemText(i, 4, TEXT("n/a"));
			m_ListThunk.SetItemText(i, 5, szTemp);
		}
        
		pThunkData++;
	}
    
}


BOOL DlgImport::IsEndOfTable(PIMAGE_IMPORT_DESCRIPTOR pImportDesc)
{
	if (0 == pImportDesc->OriginalFirstThunk &&
        0 == pImportDesc->TimeDateStamp &&
        0 == pImportDesc->ForwarderChain &&
		0 == pImportDesc->Name &&
        0 == pImportDesc->FirstThunk)
    {
        return TRUE;
    }
	return FALSE;
}


void DlgImport::OnNMClickListImport(NMHDR* pNMHDR, LRESULT* pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	// TODO: 在此添加控件通知处理程序代码
	int nIndex = m_ListImport.GetSelectionMark();
	if (nIndex != -1)
	{
		InitImportThunk(nIndex);
	}
    
	*pResult = 0;
}
